package com.dkd.manage.task.allocator.algorithm;

import com.dkd.manage.domain.Emp;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.function.Function;

@Slf4j
public class ParticleSwarmOptimization {
    private int swarmSize;
    private int iterations;

    public ParticleSwarmOptimization(int swarmSize, int iterations) {
        this.swarmSize = swarmSize;
        this.iterations = iterations;
    }

    public Map<Long, Double> optimize(List<Emp> candidates, Function<Emp, Double> fitnessFunction) {
        log.info("开始粒子群优化，候选人数: {}", candidates.size());

        Map<Long, Double> results = new HashMap<>();

        // 初始化粒子群
        List<Particle> particles = initializeParticles(candidates);

        double[] globalBestPosition = null;
        double globalBestFitness = Double.NEGATIVE_INFINITY;

        // 迭代优化
        for (int iter = 0; iter < iterations; iter++) {
            // 更新每个粒子
            for (Particle particle : particles) {
                // 评估适应度
                double fitness = fitnessFunction.apply(particle.emp);

                // 更新个体最优
                if (fitness > particle.bestFitness) {
                    particle.bestFitness = fitness;
                    particle.bestPosition = particle.position.clone();
                }

                // 更新全局最优
                if (fitness > globalBestFitness) {
                    globalBestFitness = fitness;
                    globalBestPosition = particle.position.clone();
                }

                // 更新速度和位置
                updateParticle(particle, globalBestPosition);
            }

            log.debug("粒子群优化第 {} 代完成，全局最优适应度: {}", iter + 1, globalBestFitness);
        }

        // 生成结果
        for (Particle particle : particles) {
            double optimizedScore = particle.bestFitness * (0.7 + 0.6 * Math.random());
            results.put(particle.emp.getId(), optimizedScore);
        }

        log.info("粒子群优化完成，生成 {} 个结果", results.size());
        return results;
    }

    private List<Particle> initializeParticles(List<Emp> candidates) {
        List<Particle> particles = new ArrayList<>();
        Random random = new Random();

        for (int i = 0; i < swarmSize && i < candidates.size(); i++) {
            Emp emp = candidates.get(i);
            double[] position = new double[5]; // 5维位置向量
            for (int j = 0; j < position.length; j++) {
                position[j] = random.nextDouble();
            }

            particles.add(new Particle(emp, position));
        }

        return particles;
    }

    private void updateParticle(Particle particle, double[] globalBestPosition) {
        // 简化版的粒子更新逻辑
        Random random = new Random();
        double inertia = 0.5;
        double cognitiveWeight = 1.5;
        double socialWeight = 1.5;

        for (int i = 0; i < particle.velocity.length; i++) {
            // 更新速度
            particle.velocity[i] = inertia * particle.velocity[i] +
                    cognitiveWeight * random.nextDouble() * (particle.bestPosition[i] - particle.position[i]) +
                    socialWeight * random.nextDouble() * (globalBestPosition[i] - particle.position[i]);

            // 更新位置
            particle.position[i] += particle.velocity[i];

            // 边界检查
            particle.position[i] = Math.max(0, Math.min(1, particle.position[i]));
        }
    }

    private static class Particle {
        Emp emp;
        double[] position;
        double[] velocity;
        double[] bestPosition;
        double bestFitness = Double.NEGATIVE_INFINITY;

        Particle(Emp emp, double[] position) {
            this.emp = emp;
            this.position = position;
            this.velocity = new double[position.length];
            this.bestPosition = position.clone();

            // 初始化速度
            Random random = new Random();
            for (int i = 0; i < velocity.length; i++) {
                velocity[i] = random.nextDouble() * 0.1;
            }
        }
    }
}